%% $Id: xyarrow.doc,v 2.12 1994/10/25 11:34:25 kris Exp $ %% XY-pic ``Arrows and Paths'' feature. %% Copyright (c) 1991-1994 Kristoffer H. Rose %% This file is part of the XY-pic package for graphs and diagrams in TeX. %% See the companion README and INSTALL files for further information. %% Copyright (c) 1991-1994 Kristoffer H. Rose %% The XY-pic package is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by the %% Free Software Foundation; either version 2 of the License, or (at your %% option) any later version. %% The XY-pic package is distributed in the hope that it will be useful, but %% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY %% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License %% for more details. %% You should have received a copy of the GNU General Public License along %% with this package; if not, write to the Free Software Foundation, Inc., %% 675 Mass Ave, Cambridge, MA 02139, USA. \ifx\xyloaded\undefined \input xy \fi \xyprovide{arrow}{Arrow and Path feature}{\stripRCS$Revision: 2.12 $}% {Kristoffer H.~Rose}{kris@diku.dk}% {Computer Science, University of Copenhagen, Universitetsparken~1, DK--2100 K{\o}benhavn~{\O}} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% This feature provides \XY-pic with the arrow paradigm presented in~\cite{R92:HowTPDAT}. The basic concept introduced is the "path": a connection that "starts" from $c$ (the current object), "ends" at a specified object, and may be split into several "segments" between intermediate specified objects that can be individually labelled, change style, have breaks, etc. \S??[path] is about the |\PATH| primitive, including the syntax of paths, and \S??[arrow] is about the |\ar|\footnote{This name is in conflict with the command of the same name in Karl Berry's |eplain| format. Fortunately users are unlikely to want both that and \XY-pic.} customisation of paths to draw arrows using \XY-pic directional objects. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Header:}\leavevmode \DOCHEADER \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Paths} ??=[path] \DOCMODE( \message{path,} \DOCMODE) The fundamental commands of this feature are |\PATH| and |\afterPATH| that will parse the according to the grammar in figure~??[f.path] with notes below. \begin{figure*}[tb] \begin{syntax} \multispan{3}{{\tt\string\PATH} \hfil} & interpret \multispan{3}{{\tt\string\afterPATH\string{\string}} \hfil} & interpret and then run \noalign{\nobreak\smallskip\nobreak\hrule\nobreak\smallskip\nobreak} &\iss & |~| |{| |}| & set ??!^[] to &\orr & |~| |+| |{| |}| & set ??!^[default ] &\orr & |~| |{| |}| & set ??!^[failure continuation] to &\orr & |'| & make ??!^[straight segment] &\orr & |`| & make ??!^[turning segment] &\orr & & make ??!^[last segment] \noalign{\smallskip} &\iss & & ??!^[1/4 turn] starting in &\orr & & ??!^[explicit turn] &\iss & & use default turn radius &\orr & |/| & set "turnradius" to \noalign{\smallskip} &\iss & & ??!^[segment] with and \noalign{\smallskip} &\iss & \orr\ |<| |>| & optional ??!^[slide]: in the ``above'' direction \noalign{\smallskip} &\iss & |^| & ??!^[label with ] "above" &\orr & |_| & ??!^[label with ] "below" &\orr & |||| & ??!^[break with ] at &\orr & & no more labels \noalign{\smallskip} &\iss & |-| \orr\ & label/break placed relative to the where |-| is a synonym for |<>(.5)| \noalign{\smallskip} &\iss & \orr\orr|{||}|\orr & is a ??!^[default label] &\orr & |*| & is an &\orr & |@| & is a ectional \noalign{\smallskip} &\iss & \orr\ |="||"| & optional ??!^[name for label object] \end{syntax} \caption{\protects} ??=[f.path] \end{figure*} \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Parsing:} |\afterPATH| sets up |\afterPATH@| and initialise all the actions (see note~??[] below) before invoking the actual parser. |\PATH| is just a dummy interface. \DOCMODE( \xydef@\PATH{\afterPATH{}} \xylet@\afterPATH@=\empty \xydef@\afterPATH#1{\xy@@\save@ \DN@##1{\def\afterPATH@{\restore \def\afterPATH@{##1}#1}}% \expandafter\next@\expandafter{\afterPATH@}% \let\PATHfail@@=\empty \let\PATHnext@@=\empty \let\PATHevery@@=\empty \let\PATHlast@@=\empty \let\PATHeverysub@@=\empty \let\PATHbeforelabels@@=\empty \let\PATHafter@@=\empty \xy@{\afterPATH{#1}}{\def\PATHslide@@{\z@}}% \def\PATHcontinue@@{\xyFN@\PATH@}% \xyFN@\PATH@} \DOCMODE) |\PATH@| is the parser for : it eats the until it fails and then calls the `failure continuation' which will eventually become |\empty| which ends the parsing. \HACK: The `|\ifPATHsingle@|' switch switches the parsing "off"; this is used by the graph feature to parse stand-alone sequences. \DOCMODE( \xynew@{if}\ifPATHsingle@ \xydef@\PATH@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATH@}% \else\ifPATHsingle@ \let\next@=\PATH@single \else \let\next@=\PATH@normal \fi\fi \next@} \xydef@\PATH@normal{% \ifx ~\next \DN@ ~{\xyFN@\PATHsetting@}% \else \addRQ@\ifx \next \addRQ@\DN@{\xy@'{}\xyFN@\PATHstraight@}% \else \addLQ@\ifx \next \addLQ@\DN@{\xy@`{}\xyFN@\PATHturn@}% \else\ifx \PATHfail@@\PATH@x \DN@{\xyFN@\PATHlast@}% \else \DNii@{\let\PATHfail@@=\PATH@x \xyFN@\PATH@}% \DN@{\expandafter\nextii@\PATHfail@@}% \fi\fi\fi\fi \next@} \DOCMODE) |\PATHsetting@| just reads an determining which action stuff to set and then does it---we treat the failure continuation as an action here even though it is not, strictly speaking. The four actions are explained in the appropriate notes below. \DOCMODE( \xylet@\PATHnext@@=\empty \xylet@\PATHevery@@=\empty \xylet@\PATHlast@@=\empty \xylet@\PATHeverysub@@=\empty \xylet@\PATHbeforelabels@@=\empty \xylet@\PATHafter@@=\empty \xylet@\PATHfail@@=\empty \xydef@\PATHsetting@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATHsetting@}% \else\ifx \bgroup\next \DN@##1{\xy@{~{##1}}{}\def\PATHfail@@{##1}\xyFN@\PATH@}% \else \addEQ@\ifx \next \addEQ@\DN@##1{\xy@{~={##1}}{}\def\PATHevery@@{##1}\xyFN@\PATH@}% \else \addLT@\ifx \next \addLT@\DN@##1{\xy@{~<{##1}}{}\def\PATHnext@@{##1}\xyFN@\PATH@}% \else \addGT@\ifx \next \addGT@\DN@##1{\xy@{~>{##1}}{}\def\PATHlast@@{##1}\xyFN@\PATH@}% \else \addDASH@\ifx \next \addDASH@\DN@##1{\xy@{~-{##1}}{}\def\PATHeverysub@@{##1}\xyFN@\PATH@}% \else \addPLUS@\ifx \next \addPLUS@\DN@##1{\xy@{~+{##1}}{}\def\PATHbeforelabels@@{##1}\xyFN@\PATH@}% \else \ifx /\next \DN@/##1{\xy@{~/{##1}}{}\def\PATHafter@@{##1}\xyFN@\PATH@}% \else \xyerror@{Unknown \string~ setting: \meaning\next}% {See the XY-pic arrow feature documentation for help.}% \fi\fi\fi\fi\fi\fi\fi\fi \next@} \DOCMODE) Next the setup for straight segments including the last: they set |\PATHinit@@| to initialise, \ie, slide, |\PATHextra@@| to finish after the |=<| actions, \ie, for the last to expand the |>| action, and finally |\PATHpost@@| is set to any operations to be done after the entire segment is typeset but before the next is read. |\PATHcontinue@@| is used internally to distinguish the ordinary segments from the last. \DOCMODE( \xylet@\PATHinit@@=\empty \xylet@\PATHextra@@=\empty \xylet@\PATHpost@@=\empty \xylet@\PATHcontinue@@=\empty \xydef@\PATHstraight@{% \def\PATHinit@@{\PATHinitstraight@}\def\PATHextra@@{}\def\PATHpost@@{}% \xy@@\pfromc@ \PATHafterPOS{\xyFN@\PATHsegment@}} \xydef@\PATHlast@{% \def\PATHinit@@{\PATHinitstraight@}% \def\PATHextra@@{\let\PATHcontinue@@=\afterPATH@ \addGT@\PATHaction@\PATHlast@@ \let\PATHlast@@=\empty}% \def\PATHpost@@{}% \xy@@\pfromc@ \PATHafterPOS{\xyFN@\PATHsegment@}} \xydef@\PATHinitstraight@{\xy@@{\setupDirection@ \dimen@=\PATHslide@@ \dimen@ii=-\sinDirection\dimen@ \ifPATHomitslide@@\else\advance\Xp\dimen@ii\fi \advance\Xc\dimen@ii \dimen@ii= \cosDirection\dimen@ \ifPATHomitslide@@\else\advance\Yp\dimen@ii\fi \advance\Yc\dimen@ii \PATHomitslide@@false \resetupDirection@}} \DOCMODE) Setup for turning segments is in note~??[turning segment]. A is interpreted as follows after $p$ has been set to the previous end object, $c$ to the given at the start of the segment, and |\PATHslide@@| to the slide: \DOCMODE( \xydef@\PATHslide@@{\z@} \xynew@{if}\ifPATHomitslide@@ \xydef@\PATHsegment@{% \addLT@\ifx\next \addGT@{\addLT@\DN@##1}{% \xy@{<##1>}{\dimen@=##1\relax \edef\PATHslide@@{\the\dimen@}}% \xyFN@\PATHsegment@@}% \else \let\next@=\PATHsegment@@ \fi \next@} \DOCMODE) \begin{enumerate} \item Expand |\PATHinit@@| (for straight segments this just sets up the direction and applies the ). \item Expand |\PATHaction={||}| as set using |~={||}|. \item Expand |\PATHaction<{||}| as set using |~<{||}| since last expansion, and clear it. \item Expand |\PATHextra@@| (for last segments this expands |\PATHaction>{||}| and sets |\PATHcontinue@@| to any continuation set with |~{||}|). \item Store $p,c$ as "start","end" of segment. \item Interpret (see below). \item Expand |\PATHaction-{||}| as set using |~-{||}| for each subsegment (see below). \end{enumerate} |\PATHsegment@@| performs this except the last two points: \DOCMODE( \xylet@\cfrominitial@@=\relax \xylet@\cfromfinal@@=\relax \xydef@\PATHsegment@@{\PATHinit@@ \resetbreaks \addEQ@\PATHaction@\PATHevery@@ \addLT@\PATHaction@\PATHnext@@ \let\PATHnext@@=\empty \PATHextra@@ \xy@@{\edef\cfrominitial@@{\cfromthep@}\edef\cfromfinal@@{\cfromthec@}% \edef\pfromlastbreak@@{\pfromthep@}}\resetbreaks% \def\subsegmentno@{0}\toks@={}% \DN@{\xyFN@\PATHlabels@}\expandafter\next@\PATHbeforelabels@@} \DOCMODE) |\PATHlabels@| parses all of a . This sets |\PATHlabelit@@| to the operation building the label in question. Then some parsing stores the tokens |<>(.5)| for each |-| in the an finally passes control to the kernel parser with these tokens as the head. This then in turn calls |\PATHit@| that parses and applies the chosen operation. After the last we continue with the accumulated subsegment actions. \DOCMODE( \xylet@\PATHlabelit@@=\empty \xydef@\PATHlabels@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATHlabels@}% \else \ifx ^\next % \DN@^{\xy@^{}\let\PATHlabelit@@=\PATHlabelabove@ \DNii@{}\xyFN@\PATHanchor@}% \DN@##1{\xy@^{}\let\PATHlabelit@@=\PATHlabelabove@ \DNii@{}\xyFN@\PATHanchor@}% \else \ifx _\next % \DN@_{\xy@_{}\let\PATHlabelit@@=\PATHlabelbelow@ \DNii@{}\xyFN@\PATHanchor@}% \DN@##1{\xy@_{}\let\PATHlabelit@@=\PATHlabelbelow@ \DNii@{}\xyFN@\PATHanchor@}% \else \ifx |\next \DN@|{\xy@|{}\let\PATHlabelit@@=\PATHlabelbreak@ \DNii@{}\xyFN@\PATHanchor@}% \else \let\next@=\PATHsubsegments@ \fi\fi\fi\fi \next@} \xydef@\PATHanchor@{\begingroup \toks@={}\PATHanchor@i} %\xydef@\PATHanchor@ii{\begingroup \toks@={}\PATHanchor@i} %\xydef@\PATHanchor@{\DN@{\PATHanchor@ii}% % \ifx|\next % \DN@|{\xy@|{}\let\PATHlabelit@@=\PATHlabelat@ \xyFN@\PATHanchor@ii}% % \fi \next@ } \xydef@\PATHanchor@i{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATHanchor@i}% \else\addDASH@\ifx \next \addDASH@\DN@{\expandafter\addtotoks@\expandafter{\PATHanchor@toks}% \xyFN@\PATHanchor@i}% \else \DNii@##1{\endgroup\afterPLACE{\xyFN@\PATHit@}##1}% \DN@{\expandafter\nextii@\expandafter{\the\toks@}}% \fi\fi \next@} {\xyuncatcodes \gdef\next{<>(.5)}} \xylet@\PATHanchor@toks=\next \xydef@\PATHit@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATHit@}% \else \ifx *\next \DN@*##1##{\PATHlabelit@@{##1}}% \else \addAT@\ifx\next \addAT@\DN@##1##{\PATHlabelit@@{\dir##1}}% \else \DN@{\PATHlabelit@@{}}% \fi\fi\fi \next@} \DOCMODE) The individual operations bound to |\PATHlabelit@@| are discussed as appropriate in the notes. |\PATHsubsegments@| will execute the subsegment actions built during |\PATHlabels@| plus the last subsegment (the only one if there were no breaks) as described below in note~??[]. \DOCMODE( \xydef@\PATHsubsegments@{\the\toks@ \toks@={}\xy@@{\ifx\bstartPLACE@\relax\else\def\bendPLACE@{1}\fi \pfromlastbreak@@\cfromfinal@@\setupDirection@}% \addDASH@\PATHaction@\PATHeverysub@@ \PATHpost@@ \PATHaction@/\PATHafter@@ \PATHcontinue@@} \DOCMODE) \BUG: The order of the breaks determines the order of the subsegments. This is maybe a feature. \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{notes} \note??=[] An can be either of the characters |=<>-/|. The associated is saved and used to call |\PATHaction||{||}| at specific times while parsing the : \begin{tabular}{\otherbar c\otherbar l\otherbar} \hline & applied\dots \\ \hline |=| & before every segment \\ |<| & before next segment \\ |>| & before last segment \\ |-| & for every subsegment \\ |/| & after every segment \\ \hline \end{tabular} The |=<>| actions are always expanded in that sequence after $p$ and $c$ have been set up to the proper start and end of the segment but "before" any are interpreted, the |-| action is expanded for each subsegment "after" all have been interpreted (see also note~??[straight segment]), and finally the |/| action is applied. The default |\PATHaction| macro just expands to ``|\POS| |\relax|'' thus should be of the form . The user can redefine this---in fact the |\ar| command described in \S??[arrow] below is little more than a special |\PATHaction| command and a clever defaulting mechanism. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Here is the default |\PATHaction|: \DOCMODE( \xydef@\PATHaction@default#1#2{\xy@{PATHaction#1{#2}}{}\POS#2\relax} \xylet@\PATHaction=\PATHaction@default \DOCMODE) It is called using |\PATHaction@| to expand the action control sequences back to their first: \DOCMODE( \xydef@\PATHaction@#1#2{\expandafter\PATHaction\expandafter#1\expandafter{#2}} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[default ] Defining default will insert these first in the label sequence of every . This is useful to draw connections with a `center marker' in particular with arrows, \eg, the `mapsto' example explained below can be changed into a `breakto' example: typing \begin{code} \xy*+{0}\PATH ~={**{}} ~>{\save?>*\dir{>}\restore} ~-{**\dir{-}} ~+{|*\dir{/}} '(10,1)*+{1} '(20,-2)*+{2} (30,0)*+{3} \endxy \end{code} \displaycode \noindent\unskip will typeset \docode Note, however, that what goes into |~+{|\dots|}| is and thus not a -- it is not an action in the sense explained above. \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[failure continuation] Specifying |~{||}| will set the ``failure continuation'' to . This will be inserted when the last is expected---it can even replace it or add more s, \ie, \begin{code} \xy *+{0} \PATH ~={**{}} ~-{**\dir{-}} ~{'(20,-2)*+{2} (30,0)*+{3}} '(10,1)*+{1} \endxy \end{code} \displaycode is equivalent to \begin{code} \xy *+{0} \PATH ~={**{}} ~-{**\dir{-}} '(10,1)*+{1} '(20,-2)*+{2} (30,0)*+{3} \endxy \end{code} \displaycode typesetting \docode because when |\endxy| is seen then the parser knows that the next symbol is neither of the characters |~'`| and hence that the last is to be expected. Instead, however, the failure continuation is inserted and parsed, and the is finished by the inserted material. Failure continuations can be nested: \begin{code} \xy *+{0} \PATH ~={**{}} ~-{**\dir{-}} ~{~{(30,0)*+{3}} '(20,-2)*+{2}} '(10,1)*+{1} \endxy \end{code} \displaycode will also typeset the connected digits. \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[straight segment] A ``straight segment'' is interpreted as follows: \begin{enumerate} \item First $p$ is set to the end object of the previous segment (for the first segment this is $c$ just before the path command) and $c$ is set to the starting the , and the current is applied. \item Then the |=| and |<| "segment actions" are expanded (in that sequence) and the |<| action is cleared. The resulting $p$ and $c$ become the "start" and "end" object of the segment. \item Then all (starting eith the |~+|-defined ones) are interpreted and typeset as described below. \item Finally the "subsegment actions" are expanded: If there were $n$ breaks then there are $n+1$ subsegments and thus |\PATHaction-{| |}| will be expanded $n+1$ times. The $i$th expansion, $i\in\{1,\dots,n+1\}$, will be performed with \begin{eqnarray*} p &=& b_0~|.|~b_{i-1} c &=& b_{n+1}~|.|~b_i \end{eqnarray*} where $b_i$ denotes break $i$ except that $b_0$ is the start and $b_{n+1}$ the end object of the segment. \end{enumerate} \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The code expanding the actions is part of the parsing above except for building the subsegment list which is done in |\PATHlabelbreak@| in note~??[break with ].) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subparagraph*{Example:} Typically |~=| is used to do something that will setup the |?| format to suit the segment connection which is then used by |~<| to add something to the `tail' of the path and by |~>| to add to its `head', and finally |~-| is used to actually typeset the connection beween the given breaks. For example, \begin{code} \xy*+{0}\PATH ~={**i\dir{-}} ~<{\save;?<*\dir{|}\restore} ~>{\save?>*\dir{>}\restore} ~-{**\dir{-}} '(10,1)*+{1}|b '(20,-2)*+{2} (30,0)*+{3} \endxy \end{code} \displaycode will build a `mapsto path' \docode as follows: For each segment we do the following: (1)~let |=| typeset an "invisible" connection that will make |?| behave correctly; (2)~let |<| make the start point ($p$) of the first segment be a |\dir{||}| on the edge of the original $p$ (the |;|s make us modify $p$ rather than $c$); (3)~let |>| make the end point of the last segment be a |\dir{>}| tip; and (4)~let |-| typeset each subsegment of the connection as a solid line (that will trace the invisible one set up in~(1)). Numerous variations are possible by varying what goes in which actions, \eg, \begin{code} ~={**i\dir{-} \save;?<*\dir{|}; ?>*\dir{>} \restore} ~-{**\dir{-}} \end{code} \displaycode typesets \xy*+{0}\PATH ~={**i\dir{-}, \save;?<*\dir{|}; ?>*\dir{>} \restore} ~-{**\dir{-}} '(10,1)*+{1}|b '(20,-2)*+{2} (30,0)*+{3} \endxy with every segment a separate mapsto arrow, and \begin{code} ~={**i\dir{-}} ~-{**\dir{-} \save;?<*\dir{|}; ?>*\dir{>} \restore} \end{code} \displaycode typesets \xy*+{0}\PATH ~={**i\dir{-}} ~-{**\dir{-} \save;?<*\dir{|}; ?>*\dir{>}\restore} '(10,1)*+{1}|b '(20,-2)*+{2} (30,0)*+{3} \endxy \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[segment] A "segment" is a part of a between a previous and a new "target" given as a : normally this is just a as described in~\S??g[xy.doc:pos] but it can be changed to something else by changing the control sequence |\PATHafterPOS| to be something other than |\afterPOS|. \DOCMODE( \xylet@\PATHafterPOS@default=\afterPOS \xylet@\PATHafterPOS=\PATHafterPOS@default \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[turning segment]??=[1/4 turn]??=[explicit turn] A "turning" segment is one that does not go all the way to the given but only as far as required to make a turn towards it. The $c$ is set to the actual turn object after a turning segment such that subsequent turning or other segments will start from there, in particular the last segment (which is always straight) can be used to finish a winding line. What the turn looks like is determined by the form: \begin{description} \item[] Nothing between the |`| and the is interpreted the same as giving just the last used "out" of a turn. \item[] Specifying a single $d$ is the same as specifying either of the cles $d$|^| or $d$|_|, depending on whether the specified has its center `above' or `below' the line from $p$ in the onal direction. \item[] When a full explicit cle is available then the corresponding cle object is placed such that its ingoing direction is a continuation of a straight connection from $p$ and the outgoing direction points such that a following straight (or last) segment will connect it to $c$ (with the same slide). \end{description} Here is an example using all forms of s: \begin{code} \xy <4pc,0pc>:(0,0) *+\txt{base}="base" \PATH ~={**{}} ~-{**\dir{-}?>*\dir{>}} `l (-1,-1)*{A} ^a ` (1,-1)*{B} ^b `_ul (1, 0)*{C} ^c `ul^l "base" ^d "base" ^e \endxy \end{code} \docode was typeset by \displaycode \BUG: Turns are only really resonable for paths that use straight lines like the one above. \NOTE: Always write a valid after a , otherwise any following |^| or |_| labels can confuse the parser. So if you intend the |^r| in |`^r| to be a label then write |`,^r|, using a dummy |,| ition. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% We need to keep track of the current "in" and "out" directions as well as the current radius. \DOCMODE( \xydef@\PATHlastout@@{3} \DOCMODE) The startup routine is just a selection of the two kinds of : \DOCMODE( \xydef@\PATHturn@{\afterCIRorDIAG\PATHturn@cir\PATHturn@diag} \DOCMODE) In both cases the trick is to set up a |\PATHinit@@| method that typesets the right circle segment at the right location. The simplest one is when there is a full available because that should just be used directly. The only complication is that we forbid $180^\circ$ turns: \DOCMODE( \xydef@\PATHturn@cir{\toks@={\xy@@{% \count@=\CIRin@@ \ifnum\count@<4\else\advance\count@-4\fi \count@@=\CIRout@@ \ifnum\count@@<4\else\advance\count@@-4\fi \ifnum\count@=\count@@ \xyerror@{ cannot be half or full}{% You asked for a ed segment with parallel in- and out-direction.^^J% This is not allowed because it is not possible to position it uniquely.}\fi}}% \edef\next@{{\CIRin@@}{\expandafter\noexpand\CIRorient@@}{\CIRout@@}}% \expandafter\PATHturn@i\next@} \DOCMODE) "Procedure for turns": Builds initial part of |\PATHinit@@| that computes the missing "orient" and "out" from "in" and the $c$ passed through the segment. This initial segment should set "orient" as follows: \xy <9mm,0mm>: <0mm,4mm>:: ,(1,1) *+\dir{*}!D *!LU{p} ,(0,0);(4,4)**\dir{-} ?< *!/+\jot/\composite{{.}*!/+\jot/{.}*!/+2\jot/{.}} ?> *!/-\jot/\composite{{.}*!/-\jot/{.}*!/-2\jot/{.}} ?(.6)*!/1ex/\dir{>} *^!/-1ex/{|^|} *_!/-1ex/{|_|} \endxy \ie, as the sign of inner product $\vec{pc} \cdot \hat{"in"}$, and set "out" as for the cle "in" "orient". \DOCMODE( \xydef@\PATHturn@diag{\toks@={\xy@@{% \setupDirection@ \count@=\CIRin@@ \dimen@=\xydashl@ \ABfromdiag@ \ifdim \sinDirection\A@>\cosDirection\B@ \def\CIRorient@@{\CIRacw@}% \advance\count@\ifnum\count@<6 \tw@ \else -6\fi \else \def\CIRorient@@{\CIRcw@}% \advance\count@\ifnum\count@>\@ne -\tw@ \else 6\fi \fi \edef\CIRout@@{\the\count@}}}% \edef\next@{{\CIRin@@}{}{}}% \expandafter\PATHturn@i\next@} \DOCMODE) |\PATHturn@i| is where |\PATHinit@@| is defined to do the following: \begin{itemize} \item[{??_[turni1]}] Setup the default "in", "orient", and "out" as defined by the call from the above macros. Set "radius" parameter to the current "turnradius" value. The commands in |\toks@| are run to do any last-minute fixing of the defaults. \item[{??_[turni2]}] The segment will leave $p$ in direction "in" and pretend to be meeting $c$ in direction "out". Thus the center of the cle object to be used for the actual object is located at the intersection of the line through $p+"radius"\hat{v}_"in"$ in direction $\vec{v}_"in"$ and the line through $c+"radius"\hat{v}_"out"$ in direction $\vec{v}_"out"$. Here we compute $p+R\hat{v}_"in"$ using $R="radius"$ if this is the initial turn and $R="radius"\pm"slide"$ if it is a continuation turn. \item[{??_[turni2b]}] Save $p$ and "base" for later. \item[{??_[turni3]}] Compute $c+"radius"\hat{v}_"out"$ and use the kernel |\intersect@| primitive to compute the turn circle segment center. \item[{??_[turni3b]}] However, if the intersection point lies on the `wrong side' of $p$, \ie, if $\vec{pc} \cdot "in"$ is negative, then we should not use the intersection point but the point as close to $p$ as possible because the connection from $p$ to the turn should at least have zero length---in fact we set it to have 8sp length to make sure that a sugsegment is typeset! \item[{??_[turni4]}] Modify "radius" to use for the actual circle segment by the "slide": either positively (for "orient" |_|) or negatively (for "orient" |^|), and drop the circle segment (bypassing |\cir| to use the internal settings from above). \item[{??_[turni5]}] Store in |\PATHpostpos@@| the true end of the circle segment and code to prevent the application of the "slide" for the start of the next . \item[{??_[turni6]}] Move $c$ to true beginning of the circle segment. \item[{??_[turni7]}] Restore saved $p$ and "base", and slide $p$ finally. \end{itemize} \DOCMODE( \xylet@\PATHpostpos@@=\empty \xydef@\PATHturn@i#1#2#3{% \DN@##1{\def\PATHinit@@{\xy@@{% \def\CIRin@@{#1}\def\CIRorient@@{#2}\def\CIRout@@{#3}% %?*[turni1] \ifnum\CIRin@@=8 \let\CIRin@@=\PATHlastout@@ \fi \R@=\turnradius@ ##1\relax \count@=\CIRin@@ %?*[turni2] \ifPATHomitslide@@ \dimen@=-\PATHslide@@ \ABfromdiag@ \advance\Xp-\B@ \advance\Yp\A@ \fi \enter@{\pfromthep@ \basefromthebase@}% %?*[turni2b] \dimen@=\expandafter\ifx\CIRorient@@\CIRcw@-\fi\R@ \ABfromdiag@ \advance\Xp-\B@ \advance\Yp\A@ \Xorigin=\Xp \Yorigin=\Yp %?*[turni3] \dimen@=\xydashl@ \ABfromdiag@ \Rc=\A@ \Uc=\B@ \count@=\CIRout@@ \dimen@=\expandafter\ifx\CIRorient@@\CIRcw@-\fi\R@ \ABfromdiag@ \advance\Xc-\B@ \advance\Yc\A@ \dimen@=\xydashl@ \Xp=\Xc \Yp=\Yc \ABfromdiag@ \advance\Xp-\A@ \advance\Yp-\B@ \intersect@ \count@=\CIRin@@ \dimen@=\p@ \ABfromdiag@ %?*[turni3b] \edef\next@{\expandafter\removePT@\the\A@}% \edef\nextii@{\expandafter\removePT@\the\B@}% \A@=\Xc \advance\A@-\Xorigin \B@=\Yc \advance\B@-\Yorigin \ifdim \next@\A@<-\nextii@\B@ \dontleave@ \cfromp@ \count@=\CIRin@@ \advance\count@\ifnum\count@<4 +4\else -4\fi \dimen@=\xydashl@ \Directionfromdiag@ \the\Edgec\z@ \count@=\CIRin@@ \dimen@=\expandafter\ifx\CIRorient@@\CIRcw@-\fi\R@ \ABfromdiag@ \advance\Xc-\B@ \advance\Yc\A@ \dimen@=5sp \ABfromdiag@ \advance\Xc\A@ \advance\Yc\B@ \fi \dimen@ii=\expandafter\ifx\CIRorient@@\CIRacw@-\fi\PATHslide@@ %?*[turni4] \advance\R@\dimen@ii \drop@\literal@{\hbox\bgroup\cir@i}% \Xp=\Xc \Yp=\Yc %?*[turni5] \count@=\CIRout@@ \dimen@=\expandafter\ifx\CIRorient@@\CIRacw@-\fi\Rc \ABfromdiag@ \advance\Xp-\B@ \advance\Yp\A@ \edef\PATHpostpos@@{\Xc=\the\Xp \Yc=\the\Yp \noexpand\czeroEdge@ \noexpand\PATHomitslide@@true}% \count@=\CIRin@@ %?*[turni6] \dimen@=\expandafter\ifx\CIRorient@@\CIRacw@-\fi\Rc \ABfromdiag@ \advance\Xc-\B@ \advance\Yc\A@ \czeroEdge@ \leave@ %?*[turni7] \count@=\CIRin@@ \dimen@=\PATHslide@@ \ABfromdiag@ \advance\Xp-\B@ \advance\Yp\A@ \edef\PATHlastout@@{\CIRout@@}% \count@=\CIRout@@ \dimen@=\xydashl@ \Directionfromdiag@}}}% \expandafter\next@\expandafter{\the\toks@}\toks@={}% \def\PATHextra@@{}% \def\PATHpost@@{\xy@@\PATHpostpos@@}% \xyFN@\PATHturn@ii} \DOCMODE) The final macro takes care of the v2.6 format for changing "turnradius": using |/| right after the . \DOCMODE( \xydef@\PATHturn@ii{% \ifx /\next \DN@ /{\afterassignment\nextii@\dimen@=}% \DNii@{% \edef\next@{\noexpand\xy@@{\edef\noexpand\turnradius@{\the\dimen@}}}\next@ \xy@@\pfromc@ \PATHafterPOS{\xyFN@\PATHsegment@}}% \else \DN@{\xy@@\pfromc@ \PATHafterPOS{\xyFN@\PATHsegment@}}\fi \next@} \DOCMODE) This just stores a vector of the specified lenght in $|<|A|,|B|>|$ thus acting as an optimised version of |\Directionfromdiag@|: \DOCMODE( \xydef@\ABfromdiag@{\ifcase\count@\relax \A@=-.7071\dimen@ \B@=-.7071\dimen@ \or \A@=\z@ \B@=-\dimen@ \or \A@=+.7071\dimen@ \B@=-.7071\dimen@ \or \A@=\dimen@ \B@=\z@ \or \A@=+.7071\dimen@ \B@=+.7071\dimen@ \or \A@=\z@ \B@=+\dimen@ \or \A@=-.7071\dimen@ \B@=+.7071\dimen@ \or \A@=-\dimen@ \B@=\z@ \else\xybug@{impossible ?}\fi} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The default used for "turnradius" can be set by the operation \begin{defs1} |\turnradius| |{||}|\cr \end{defs1} \noindent\unskip that works like the kernel |\objectmargin| etc. commands; it defaults to 10pt. \DOCMODE( \xydef@\turnradius@{10pt} \xydef@\turnradius{\afterADDOP{\Addop@@\turnradius@}} \DOCMODE) \begin{exercise} Typeset \begin{code} \xy *+{A}*\cir<10pt>{}="me" \PATH ~={**{}} ~-{**dir{-}} `ul^ur,"me" "me" |>*:(1,-.15)\dir{>} \endxy \end{code} $$\docode$$ using s. \answertext{Here is what the author did:??c[\cir]} \answercode \answertext\displaycode \answertext{The trick is getting the arrow head right: the |:| modifier to the explicit {\tt\string\dir} does that.} \end{exercise} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[last segment] The last segment is exactly as a straight one except that the |>| action (if any) is executed (and cleared) just after the |<| action. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (The code implementing this is merged with the parsing.) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[slide] ``Sliding'' a segment means moving each of the $p,c$ objects in the direction perpendicular to the current direction at each. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% (The code implementing this is merged with the parsing, using the |\PATHslide@@| control sequence to hold the current slide.) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[label with ] Labelling means that is dropped relative to the current segment using a |?| ition. This thus depends on the user setting up a connection with a |**| as one of the actions---typically the~|=| action is used for this (see note~??[straight segment] for the details). The only difference between |^| and |_| is that they shift the label in the |^| respectively |_| direction; for straight segments it is placed in the ``superscript'' or ``subscript'' position. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The operations used by |\PATHlabels@| to put labels above and below (with |^| and |_|) are trivial, taking two arguments and placing the label immediately; for convenience the |\drop| head are named separately such that they may be redefined: \DOCMODE( \xydef@\PATHlabelabove@#1#2{\xy@@\save@ \droplabel@\belowDirection@{#1}{#2}% \xyFN@\PATHlabelalias@} \xydef@\PATHlabelbelow@#1#2{\xy@@\save@ \droplabel@\aboveDirection@{#1}{#2}% \xyFN@\PATHlabelalias@} %\xydef@\PATHlabelat@#1#2{\W@{eat}\xy@@\save@ \droplabel@\eat@{#1}{#2}% % \xyFN@\PATHlabelalias@} \xydef@\droplabel@#1#2#3{% \xy@@{\enter@\DirectionfromtheDirection@}% \DN@{#2}\ifx\next@\empty \xy@@ix@{\labelbox{#3}}% \else \xy@@ix@{#2{#3}}\fi \xy@@{% \setbox\z@=\expandafter\object\the\toks9 % \advance\Lc\labelmargin@ \advance\Rc\labelmargin@ \advance\Dc\labelmargin@ \advance\Uc\labelmargin@ \A@=\Xc \B@=\Yc #1\xydashl@ \the\Edgec\thr@@ \advance\A@-\Xc \advance\B@-\Yc \advance\Xc 2\A@ \advance\Yc 2\B@ \ht\z@=\Uc \dp\z@=\Dc \setbox\lastobjectbox@=\hbox{\kern\labelmargin@\Drop@@\kern\labelmargin@}% \drop@{\box\lastobjectbox@}{}% \leave@}}% \DOCMODE) (These emulate the effect of the s |!C| |+<|2"labelmargin"|>| |!P| where , are |^|,|_| for |^|-labels and |_|,|^| for |_|-labels). \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Labels will be separated from the connection by the "label"\-"margin" that you can set with the operation \begin{defs1} |\labelmargin| |{||}| \end{defs1} \noindent\unskip that works like the kernel |\objectmargin| command; in fact "labelmargin" defaults to use "objectmargin" if not set. \DOCMODE( \xylet@\labelmargin@=\objectmargin@ \xydef@\labelmargin{\afterADDOP{\Addop@@\labelmargin@}} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[break with ]??=[piece] Breaking means to ``slice a hole'' in the connection and insert there. This is realized by typesetting the connection in question in "subsegments", one leading to the break and one continuing after the break as described in notes~??[] and~??[straight segment]. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% When a is finished then its subsegments are built. The trick is to collect the break actions in a queue in order to handle all the subsegments in one go as described above. Care has been taken to expand everything at the right time: ??_[break1]~we |\drop| the break object immediately since its is the current $c$. ??_[break2]~we continue by incrementing the break number~$i$ and define a control sequence |\cmergebreak|$i$|@| that will merge the $c$ when expanded with the break object. ??_[break3]~Finally we add the operations to be performed for the subsegment "into" this break to |\toks@|. \DOCMODE( \xylet@\pfromlastbreak@@=\empty \xylet@\breakcount@=\relax \def\next{\cfrominitial@@} \expandafter\let\csname cfrombreak0@\endcsname=\next \xydef@\resetbreaks{% \xy@@{\let\bstartPLACE@=\relax \let\bendPLACE@=\relax}} \xydef@\invisbreaks{\xy@@{\def\bstartPLACE@{}}} \xydef@\initbreaks{\xy@@{\ifx\bstartPLACE@\relax \def\bstartPLACE@{0}\def\bendPLACE@{1}\fi}} \xydef@\lastbreaks{\xy@@{\ifx\bstartPLACE@\relax \def\bstartPLACE@{0}\fi\def\bendPLACE@{1}}} \xylet@\bstartPLACE@=\relax \xylet@\bendPLACE@=\relax %\xydef@\PATHlabelbreak@#1#2{% % \DN@{#1}\ifx\next@\empty \drop\labelbox{#2}% %?*[break1] % \else \drop#1{#2}\fi \xy@@{\save@}% % \count@=\subsegmentno@ \advance\count@\@ne %?*[break2] % \edef\subsegmentno@{\the\count@}% % \DN@##1{% % \xy@@{\expandafter\edef\csname cmergebreak##1@\endcsname % {\DirectionfromtheDirection@ \cmergethecz@}}% % \addtotoks@{% % \xy@@{\pfromlastbreak@@ \cfromfinal@@ %?*[break3] % \csname cmergebreak##1@\endcsname \infinitize@+}% % \addDASH@\PATHaction@\PATHeverysub@@ % \xy@@{\cfrominitial@@ % \csname cmergebreak##1@\endcsname \infinitize@-% % \edef\pfromlastbreak@@{\pfromthec@}}}}% % \expandafter\next@\expandafter{\subsegmentno@}% % \xyFN@\PATHlabelalias@} \xydef@\PATHlabelbreak@#1#2{% \DN@{#1}\ifx\next@\empty \drop\labelbox{#2}% %?*[break1] \else \drop#1{#2}\fi \xy@@{\save@}% \count@=\subsegmentno@ \advance\count@\@ne %?*[break2] \edef\subsegmentno@{\the\count@}% \DN@##1##2##3##4{% \addtotoks@{% \xy@@{\ifx\bstartPLACE@\relax\def\bstartPLACE@{0}% \else\edef\bstartPLACE@{\bendPLACE@}\fi \def\bendPLACE@{##4}}}% \xy@@{\expandafter\edef\csname cmergebreak##1@\endcsname {\DirectionfromtheDirection@ \cmergethecz@}% \expandafter\def\csname cfrombreak##3@\endcsname{\cfromfinal@@}% \expandafter\edef\csname cfrombreak##1@\endcsname {\DirectionfromtheDirection@ \cfromthec@}}% \addtotoks@{% \xy@@{\pfromlastbreak@@ \csname cfrombreak##3@\endcsname %?*[break3] \csname cmergebreak##1@\endcsname }% \addDASH@\PATHaction@\PATHeverysub@@ \xy@@{\csname cfrombreak##2@\endcsname \csname cmergebreak##1@\endcsname \edef\pfromlastbreak@@{\pfromthec@}\def\bstartPLACE@{##4}}}}% \count@@=\count@ \advance\count@\@ne \advance\count@@\m@ne \ifx\PLACEf@\empty \edef\tmp@{{\subsegmentno@}{\the\count@@}{\the\count@}{}}% \else \edef\tmp@{{\subsegmentno@}{\the\count@@}{\the\count@}\PLACEf@}% \fi \expandafter\next@\tmp@ \xyFN@\PATHlabelalias@} \xydef@\cmergethecz@{% \noexpand\cmergez@{\the\Yc}{\the\Xc}{\the\Dc}{\the\Uc}{\the\Lc}{\the\Rc}} %\xydef@\cmergez@#1#2#3#4#5#6{\the\Edgec4% % \A@=#2\relax \B@=#1\relax % \DN@{\zeroEdge}\expandafter\DNii@\expandafter{\the\Edgec}% % \ifx\next@\nextii@ \else % \Lc=-\A@ \advance\Lc+#5\advance\Lc+\Xc \ifdim\Lc<\z@ \Lc=\z@ \fi % \Rc=+\A@ \advance\Rc+#6\advance\Rc-\Xc \ifdim\Rc<\z@ \Rc=\z@ \fi % \Dc=-\B@ \advance\Dc+#3\advance\Dc+\Yc \ifdim\Dc<\z@ \Dc=\z@ \fi % \Uc=+\B@ \advance\Uc+#4\advance\Uc-\Yc \ifdim\Uc<\z@ \Uc=\z@ \fi % \Edgec={\rectangleEdge}% % \fi} \xydef@\cmergez@#1#2#3#4#5#6{\the\Edgec4% \A@=#2\relax \B@=#1\relax \Lc=-\A@ \advance\Lc+#5\advance\Lc+\Xc \ifdim\Lc<\z@ \Lc=\z@ \fi \Rc=+\A@ \advance\Rc+#6\advance\Rc-\Xc \ifdim\Rc<\z@ \Rc=\z@ \fi \Dc=-\B@ \advance\Dc+#3\advance\Dc+\Yc \ifdim\Dc<\z@ \Dc=\z@ \fi \Uc=+\B@ \advance\Uc+#4\advance\Uc-\Yc \ifdim\Uc<\z@ \Uc=\z@ \fi \DN@{\Edgec={\rectangleEdge}}% \ifdim\Lc=\z@ \ifdim\Uc=\z@ \ifdim\Rc=\z@ \ifdim\Dc=\z@ \DN@{}\fi\fi\fi\fi \next@ } \xydef@\infinitize@#1{\the\Edgec4% \dimen@=\Xc \advance\dimen@-\Xp \def\next{TT}% \DN@{\zeroEdge}\expandafter\DNii@\expandafter{\the\Edgec}% % \ifx\next@\nextii@ \the\Edgec\@ne \ifInside@\def\next{TF}\fi\fi \ifx\next@\nextii@ \def\next{TF}\fi \if\next \ifdim\dimen@<\z@ \Lc=\Xc \advance\Lc-\Xmin \advance\Lc1pc % \else \ifdim\dimen@>\z@ \Rc=\Xmax \advance\Rc-\Xc \advance\Rc1pc \fi\fi \dimen@=\Yc \advance\dimen@-\Yp \ifdim\dimen@<\z@ \Dc=\Yc \advance\Dc-\Ymin \advance\Dc1pc % \else\ifdim\dimen@>\z@ \Uc=\Ymax \advance\Uc-\Yc \advance\Uc1pc \fi\fi \Edgec={\rectangleEdge}\fi \let\next=\relax} \DOCMODE) \HACK: The merging takes special care to avoid changing things when merging with zero-sized objects that are `under' the current one. \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[default label] Unless is a full-fledged (by using the |*| form), it is typeset using a |\labelbox| object (initially similar to |\objectbox| of basic \XY-pic but using |\labelstyle| for the style). \REMARK: You can only omit the |{}|s around single letters, digits, and control sequences. \DOCMODE( \xylet@\labelstyle=\scriptstyle \xydef@\labelbox#1{\hbox{$\m@th\labelstyle{#1}$}} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[name for label object] A label is an object like any other in the \XY-picture. Inserting an |="||"| saves the label object as |"||"| for later reference. \begin{exercise} Typeset \begin{code} \xy(0,0) \ar @{-->} (30,7) ^A="a" \POS(10,12)*+\txt{label} \ar "a" \endxy \end{code} $$\docode$$ \answercode \answertext{The author did \displaycode} \end{exercise} \DOCMODE( \xydef@\PATHlabelalias@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\PATHlabelalias@}% \else \addEQ@\ifx \next \addEQ@\DN@"##1"{\savealias@{##1}\xyFN@\PATHlabelalias@}% \else \DN@{\xy@@\leave@ \PATHlabels@}\fi\fi \next@} {\xyuncatcodes \gdef\next#1{\POS!C="#1"\relax}} \xylet@\savealias@=\next \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \end{notes} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection{Arrows} ??=[arrow] \begin{figure*}[tb] \vfil \begin{syntax} \multispan{3}{{\tt\string\ar} \hfil} & make along \noalign{\nobreak\smallskip\nobreak\hrule\nobreak\smallskip\nobreak} &\iss &
\star & has the s \noalign{\smallskip} &\iss & |@| & use of arrow &\orr & |@| |{| |}| & ??!^[build arrow] using of a standard stem and for the head &\orr & |@| |{| |}| & ??!^[build arrow] using of , , and other as arrow tail, stem, and head (in that order) &\orr & |@/| |/| & ??!^[curve] arrow the ance towards &\orr & |@'| |{| |}| & ??!^[curve arrow using control points] &\orr & |@*| |{| \star\ |}| & use ??!^[object s] for all objects &\orr & |||| & break each segment at with &\orr & |^| \orr\ |_| & label each segment at with \noalign{\smallskip} &\iss & \orr\ |^| \orr\ |_| \orr\ |0| \orr\ |1| \orr\ |2| \orr\ |3| & : plain, above, below, double, or triple \noalign{\smallskip} &\iss & \star & directional named as the sequence of s &\orr & & ??!^[any ectional] \noalign{\smallskip} &\iss & |<|\orr|>|\orr|(|\orr|)|\orr||||\orr|'|\orr|`|\orr|+|\orr|/| & recognised tip characters &\orr & \orr\ & more tip characters \noalign{\smallskip} &\iss & \star & directional named as the sequence of s &\orr & & ??!^[any ectional] \noalign{\smallskip} &\iss & |-|\orr|.|\orr|~|\orr|=|\orr|:| & recognised connector characters \end{syntax} \caption{\protects.}??=[f.arrow] \vfil \end{figure*} \DOCMODE( \message{\string\ar,} \DOCMODE) Arrows are paths with a particularly easy syntax for setting up arrows with "tail", "stem", and "head" in the style of~\cite{R92:HowTPDAT}. This is provided by a single ation the syntax of which is described in figure~??[f.arrow] (with the added convention that a raised `\star' means 0 or more repetitions of the preceeding nonterminal). \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Parsing:} The |\ar| command effectively translates the into a |\PATH| command that initialises the tail, stem, and head of it as required to get the desired . The translation of the is saved in the following variables: \DOCMODE( \xylet@\arvariant@@=\empty \xylet@\artail@@=\empty \xylet@\arstem@@=\empty \xylet@\arhead@@=\empty \xylet@\armodifiers@@=\empty \xylet@\arlabels@@=\empty \xylet@\arinit@@=\empty \xylet@\arexit@@=\empty \xylet@\arcomponent@@=\relax \xylet@\arcomponenttype@@=\relax \xylet@\afterarr@@=\relax \DOCMODE) |\ar| stores the defaults: \DOCMODE( \xydef@\ar{% \let\arvariant@@=\empty \def\artail@@{ {}}% \edef\arstem@@{\arvariant@@{-}}% \edef\arhead@@{\arvariant@@{>}}% \def\armodifiers@@{}% \def\arlabels@@{}% \def\arinit@@{}% \def\arexit@@{}% \xyFN@\arr@} \DOCMODE) |\arr@| is where we parse the sequence of s and continue with typesetting the arrow afterwards. \DOCMODE( \xydef@\arr@{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\arr@}% \else \addAT@\ifx\next \addAT@\DN@{\xyFN@\arr@form}% \else\ifx |\next \DN@ |{\arr@anchor|}% \else\ifx ^\next \DN@ ^{\arr@anchor^}% \else\ifx _\next \DN@ _{\arr@anchor_}% \else \let\next@=\arr@x \fi\fi\fi\fi\fi \next@} \DOCMODE) \NOTE: Makes use of the "new compilation principle" to parse a vacuously\dots \DOCMODE( \xydef@\arr@anchor#1{\begingroup \def\PATHlabelit@@##1##2{% \DN@####1{\endgroup\expandafter\def\expandafter\arlabels@@ \expandafter{\arlabels@@ ####1}}% \expandafter\next@\expandafter{\the\toks@*##1{##2}}\xyFN@\arr@}% \toks@={#1}% \def\xy@##1##2{\addtotoks@{##1}}\let\oxy@=\xy@ \let\xy@@ix@=\eat@ \DNii@{}\xyFN@\PATHanchor@} \DOCMODE) |\arr@form| handles one : \DOCMODE( \xydef@\arr@form{% \ifx \space@\next \expandafter\DN@\space{\xyFN@\arr@form}% \else\ifx ^\next \DN@ ^{\xyFN@\arr@i}\edef\arvariant@@{\string^}% \else\ifx _\next \DN@ _{\xyFN@\arr@i}\edef\arvariant@@{\string_}% \else\ifx 0\next \DN@ 0{\xyFN@\arr@i}\def\arvariant@@{0}% \else\ifx 1\next \DN@ 1{\xyFN@\arr@i}\def\arvariant@@{1}% \else\ifx 2\next \DN@ 2{\xyFN@\arr@i}\def\arvariant@@{2}% \else\ifx 3\next \DN@ 3{\xyFN@\arr@i}\def\arvariant@@{3}% \else\ifx \bgroup\next \let\next@=\arr@i \else\ifx *\next \DN@ *{\arr@modifiers}% \else\ifx /\next \let\next@=\arr@curveslash \else\ifx '\next \DN@ '{\arr@curve}% \else \let\next@=\arr@error \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next@} \xydef@\arr@error#1{\xyerror@{Illegal ation (\meaning\next)}{}% \xyFN@\arr@} \DOCMODE) |\arr@i| sets the remaining defaults and then allows |\arr@ii|-|iv| to pick up any tail, stem, and head using a |$| as terminator. \DOCMODE( \xydef@\arr@i{% \ifx \bgroup\next \let\arcomponent@@=\arr@ii \let\arcomponenttype@@=\artip@ \DN@##1{\xyFN@\arcomponent@##1$}% \else \DN@{\xyFN@\arr@}% \fi \next@} \xydef@\arr@ii{% \ifx $\next \edef\arstem@@{\arvariant@@{-}}\let\next@=\arr@iv \else \expandafter\def\expandafter\artail@@\expandafter{\the\toks@}% \let\arcomponent@@=\arr@iii \let\arcomponenttype@@=\arconn@ \DN@{\xyFN@\arcomponent@}\fi \next@} \xydef@\arr@iii{% \expandafter\def\expandafter\arstem@@\expandafter{\the\toks@}% \let\arcomponent@@=\arr@iv \let\arcomponenttype@@=\artip@ \xyFN@\arcomponent@} \xydef@\arr@iv{% \expandafter\def\expandafter\arhead@@\expandafter{\the\toks@}% \ifx $\next \DN@ ${\xyFN@\arr@}% \else \xyerror@{illegal : \meaning\next\space not valid}{}\fi \next@} \DOCMODE) |\arr@x| is the final macro that passes control to the interpreter. It is a bit clumsy because we must pass the right character tokens; it could definitely be more efficient by calling internals directly\dots \DOCMODE( \xydef@\arr@x{% \let\PATHlabelbreak@@=\arlabelbreak@ \toks@={\arr@PATH}% \expandafter\addtotoks@\expandafter{\expandafter{\artail@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\arstem@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\arhead@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\armodifiers@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\arinit@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\arexit@@}}% \expandafter\addtotoks@\expandafter{\expandafter{\arlabels@@}}% \addtotoks@{\afterarr@@}% \expandafter\DNii@\expandafter{\the\toks@}\toks@={}% \nextii@} %{\xyuncatcodes \gdef\next#1#2#3#4#5#6#7#8{\afterPATH{#8}% % ~={#5\invisbreaks\connect i#4\dir#2\resetbreaks}% % ~<{\arsegment{?<*#4\dir#1}0}% % ~>{\arsegment{?>*#4\dir#3}1}% % ~-{\initbreaks\connect #4\dir#2}% % ~/{#6\resetbreaks}% % ~+{#7}}} {\xyuncatcodes \gdef\next#1#2#3#4#5#6#7#8{\afterPATH{#8}% ~={#5\invisbreaks\connect i#4\dir#2\resetbreaks}% ~<{\arsegment{?<*#4\dir#1}0}% ~>{\arsegment{?>*#4\dir#3}1}% ~-{\initbreaks\connect #4\dir#2}% ~/{#6}% ~+{#7}}} \xylet@\arr@PATH=\next \xylet@\artmp@@=\relax \xydef@\arsegment#1#2{\xy@@{\enter@\cfromthec@}% \POS#1\relax \xy@@{\edef\tmp@{\cmergethecz@}\leave@}% \ifcase#2\xy@@{\setupDirection@ \swap@ \tmp@ \infinitize@-\swap@}% \else \xy@@{\tmp@ \setupDirection@ \infinitize@+}\fi} \DOCMODE) s and ectors are interpreted by these that leave any in |\toks@ii| and the sequence of s or s characters in |\toks@|: The work is really done in |\arcomponent@| that builds |\toks@| with something conforming to the |\arcomponenttype@@| and then passes control to |\arcomponent@@|: \DOCMODE( \xydef@\arcomponent@{% \ifx ^\next \toks@ii={^}\DN@ ^{\xyFN@\arcomponent@i}% \else\ifx _\next \toks@ii={_}\DN@ _{\xyFN@\arcomponent@i}% \else\ifx 1\next \toks@ii={1}\DN@ 1{\xyFN@\arcomponent@i}% \else\ifx 2\next \toks@ii={2}\DN@ 2{\xyFN@\arcomponent@i}% \else\ifx 3\next \toks@ii={3}\DN@ 3{\xyFN@\arcomponent@i}% \else\ifx \bgroup\next \expandafter\toks@ii\expandafter{\arvariant@@}% \let\next@=\arcomponent@i \else\ifx *\next \DN@*##1##{\arcomponent@ii{##1}}% \else \expandafter\toks@ii\expandafter{\arvariant@@}\toks@={}% \let\next@=\arcomponenttype@@ \fi\fi\fi\fi\fi\fi\fi \next@} \xydef@\arcomponent@i#1{\toks@={#1}\arcomponent@x} \xydef@\arcomponent@ii#1#2{\toks@={*#1{#2}}\xyFN@\arcomponent@@} \xydef@\artip@{% \addGT@\ifx\next \addGT@\addtotoks@ \addGT@\DN@{\xyFN@\artip@}% \else\addLT@\ifx\next \addLT@\addtotoks@ \addLT@\DN@{\xyFN@\artip@}% \else\ifx (\next \addtotoks@(\DN@({\xyFN@\artip@}% \else\ifx )\next \addtotoks@)\DN@){\xyFN@\artip@}% \else\ifx |\next \addtotoks@|\DN@|{\xyFN@\artip@}% \else\addLQ@\ifx\next \addLQ@\addtotoks@ \addLQ@\DN@{\xyFN@\artip@}% \else\addRQ@\ifx\next \addRQ@\addtotoks@ \addRQ@\DN@{\xyFN@\artip@}% \else\addPLUS@\ifx \next \addPLUS@\addtotoks@ \addPLUS@\DN@{\xyFN@\artip@}% \else\ifx /\next \addtotoks@/\DN@/{\xyFN@\artip@}% \else\ifcat A\noexpand\next \DN@##1{\addtotoks@{##1}\xyFN@\artip@}% \else\ifx\space@\next \addtotoks@{ }\expandafter\DN@\space{\xyFN@\artip@}% \else \let\next@=\arcomponent@x \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next@} \xydef@\arconn@{% \addDASH@\ifx\next \addDASH@\addtotoks@ \addDASH@\DN@{\xyFN@\arconn@}% \else\addEQ@\ifx\next \addEQ@\addtotoks@ \addEQ@\DN@{\xyFN@\arconn@}% \ifx\arvariant@@\empty \def\arvariant@@{2}\fi \else\addDOT@\ifx\next \addDOT@\addtotoks@ \addDOT@\DN@{\xyFN@\arconn@}% \else\ifx :\next \addtotoks@:\DN@:{\xyFN@\arconn@}% \ifx\arvariant@@\empty \def\arvariant@@{2}\fi \else\ifx ~\next \addtotoks@~\DN@~{\xyFN@\arconn@}% \else \let\next@=\arcomponent@x \fi\fi\fi\fi\fi \next@} \xydef@\arcomponent@x{% \DN@##1{\toks@=\expandafter{\the\toks@ii{##1}}}% \expandafter\next@\expandafter{\the\toks@}% \xyFN@\arcomponent@@} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \begin{notescontd} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[build arrow] Building an is simply using the specified directionals (using |\dir| of~\S??g[xy.doc:objectlib.directionals]) to build a path: the first becomes the "??w![arrow tail]" of the arrow, the ection in the middle becomes the "??w![arrow stem]", and the second becomes the "??w![arrow head]". If a is given before the |{| then that variant |\dir| is used for all three. For example, \begin{code} \xy\ar @^{(->} (20,7)\endxy \end{code} \displaycode typesets $$\docode$$ \begin{exercise} Typeset these arrows: \begin{code} \xy ;<1pc,0pc>: \POS(0,0)*+{A} \ar +(-2,3)*+{A'}*\cir{} \ar @2 +( 0,3)*+{A''}*\cir{} \ar @3 +( 2,3)*+{A'''}*\cir{} \POS(6,0)*+{B} \ar @1{||.>>} +(-2,3)*+{B'}*\cir{} \ar @2{||.>>} +( 0,3)*+{B''}*\cir{} \ar @3{||.>>} +( 2,3)*+{B'''}*\cir{} \endxy \end{code} $$\docode$$ \answertext{Here is the entire \XY-picture of the exercise:} \answercode \answertext\displaycode \answertext{The first batch use the default |{->}| specification.} \end{exercise} The above is a flexible scheme when used in conjunction with the kernel |\newdir| to define all sorts of arrowheads and -tails. For example, \begin{code} \newdir{|>}{!/4.5pt/\dir{|} *:(1,-.2)\dir^{>} *:(1,+.2)\dir_{>}} \end{code} \displaycode \gdocode defines a new arrow tip that makes \begin{code} \xy (0,0)*+{A} \ar @{=|>} (20,3)*+{B} \endxy \end{code} \displaycode typeset $$\docode$$ Notice that the fact that the directional uses only characters means that it blends naturally with the existing tips. \begin{exercise} Often tips used as `tails' have their ink on the wrong side of the point where they are placed. Fortunately space is also a so we can define |\dir{ >}| to generate a `tail' arrow. Do this such that \begin{code} \xy (0,0)*+{A}="a", (20,3)*+{B}="b" \ar @{>->} "a";"b" < 2pt> \ar @{ >->} "a";"b" <-2pt> \endxy \end{code} \displaycode typesets \newdir{ >}{{}*!/-5pt/\dir{>}} \docode \begin{code} \newdir{ >}{{}*!/-5pt/\dir{>}} \end{code} \answercode \answertext{The author used \displaycode} %\newdir{ |>}{\dir{|} % *!/-4.5pt/:(1,-.2)\dir^{>} % *!/-4.5pt/:(1,+.2)\dir_{>}} \end{exercise} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[any ectional] Specifying a as a or means that |\dir| is used for that or . For example, \begin{code} \xy\ar @{<^{|}>} (20,7)\endxy \end{code} \displaycode typesets $$\docode$$ When using this you must specify a |{}| dummy ectional in order to ignore one of the tail, stem, or tip components, \eg, \begin{code} \xy\ar @{{}{+}>} (20,7)\endxy \end{code} \displaycode typesets $$\docode$$ In particular |*| is a so any can be used for either of the tail, stem, or head component: \begin{code} \xy\ar @{*{x}*{y}*{z}} (20,7)\endxy \end{code} \displaycode typesets $$\docode$$ \NOTE: A |*| introduces an whereas the directional `$\xy*+!<0pt,-\jot>\dir{*}\endxy$' is typeset by the |{*}|. \begin{exercise} Typeset \begin{code} \ar @{>>*\composite{\dir{x}*\dir{+}}<<} (20,7) \endxy \end{code} $$\docode$$ using only one |\ar| command. \answertext{The author used} \answercode \answertext\displaycode \end{exercise} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[curve] "Curving" the arrow by $|/|d\ell|/|$, where $d$ is a and $\ell$ a sion, makes the stem a curve which is similar to a straight line but has had it's center point `dragged' the distance~$\ell$ in~$d$: \begin{code} \POS (0,10) *\cir<2pt>{} ="a" , (20,-10)*\cir<2pt>{} ="b" \POS"a" \ar @/^1ex/ "b"|\uparrow \POS"a" \ar @/_1ex/ "b"|\downarrow \POS (20,10) *\cir<2pt>{} ="a" , (40,-10)*\cir<2pt>{} ="b" \POS"a" \ar @/u1ex/ "b"|u \POS"a" \ar @/d1ex/ "b"|d \endxy \end{code} $$\docode$$ was typeset by \displaycode This is really just a shorthand for curving using the more general form described next: $|@/|d\ell|/|$ is the same as |@'{ @+{**{} ?+/|$d~2\ell~$|/} }| which makes the (quadratic) curve pass through the point defined by the |**{} ?+/|$d\ell$|/|. \DOCMODE( \xydef@\arr@curveslash/#1/{\expandafter\arr@curve\arr@slashing{#1}} {\xyuncatcodes \gdef\next#1{{**{} ?+/#1/+/#1/ @+c}}} \xylet@\arr@slashing=\next \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[curve arrow using control points] The second curve form is the more general one where more than one control point can be defined. The kernel stack is used for this purpose: the should be a pushing the control points in sequence on the stack: with the sequence $c_1,\dots,c_k$ of control inates this results in the |@'{ @+| c_1 \dots |@+| c_k |}| See the curve extension described in~\S??g[:curve] for the way the control points are used. \begin{exercise} Typeset the `balloon arrow' \begin{code} \xy*{\bullet}="b" @'{@+(10,10) @+(0,20) @+(-10,10)} "b" \endxy \end{code} $$\docode$$ "Hint": it uses a curve with three control points. \answercode \answertext{The author used \displaycode} \end{exercise} \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Curving simply inserts |*\crvs| first in the stem such that |\crvs| is used instead of |\dir|. The only tricky bit is to put the control points on the stack. \DOCMODE( \xydef@\arr@curve#1{\curve@check \setcurvearrowinit@\arinit@@{#1}% \setcurvearrowexit@\arexit@@ \DN@##1{\def\arstem@@{*\crvs##1}}% \expandafter\next@\expandafter{\arstem@@}% \xyFN@\arr@} {\xyuncatcodes \gdef\next#1#2{\def#1{\save @(,#2\restore}}} \xylet@\setcurvearrowinit@=\next {\xyuncatcodes \gdef\next#1{\def#1{\POS @i @) }}} \xylet@\setcurvearrowexit@=\next \xydef@\curve@check{% \xyerror@{Formation @ only available when curve extension loaded}{}} \xywithoption{curve}{\let\curve@check=\relax} \DOCMODE) \TODO: The parsing is trivial and should be extended to include more exotic control point forms. \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \note??=[object s] A |@*{|\dots|}| formation defines what object s should be used when building objects that are part of the arrow. This is mostly useful in conjunction with extensions that define additional |[||]| modifiers, \eg, if a |[red]| changes the colour of an object to red then |@*{[red]}| will make the entire arrow red. \DOCMODE( \xydef@\arr@modifiers#1{\def\armodifiers@@{#1}\xyFN@\arr@} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \end{notescontd} All the features of s described above are available for arrows. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \subsection*{End \& log} \DOCMODE( \xyendinput % $Log: xyarrow.doc,v $ % Revision 2.12 1994/10/25 11:34:25 kris % Interim release just before v3 [works with AMS-LaTeX 1.2]... % Revision 2.11 1994/07/05 10:37:32 kris % Third 3beta release [bug fixes]. % Experimental graph feature included (for ECCT-94 presentation). % Revision 2.10 1994/06/15 12:55:07 kris % Second 3beta release: bug fixes. % Revision 2.9 1994/06/09 14:59:19 kris % Release 3beta. % Revision 2.8 1994/04/08 04:30:00 kris % Second (bug fix) 3alpha release. % Revision 2.7 1994/03/08 10:25:18 kris % Release 3alpha. % Revision 2.6.9.1 1994/03/07 04:22:46 kris % Last internal 3alpha and pre-2.7 release. % NEW for version 2.7 based of path and arrow code in xypic.doc 2.6.1.1. \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Tell Emacs how we are formatted: % Local Variables: % mode:latex % fill-prefix:"\t" % fill-column:77 % paragraph-separate:"^[ \t\f]*$\\|^[^\t]\\|\\\\\\\\\\|\\$\\$\\|[^\n\\\\][%&]" % paragraph-start:"^[ \t\f]*$\\|^[^\t]\\|\\\\\\\\\\|\\$\\$\\|[^\n\\\\][%&]" % End: